//
// Created by xwt
//

#ifndef AGENT_CFG_HPP
#define AGENT_CFG_HPP
#include <string>
#include <iostream>
#include <utility>
#include <nlohmann/json.hpp>

namespace anbantech {
#define SIZE_KB 1024
#define SIZE_MB (SIZE_KB*1024)
#define SIZE_64KB (SIZE_KB*64)
#define SIZE_8MB (SIZE_MB*8)

    class agent_cfg{
    private:
        nlohmann::json payload_json_;
    public:
        char* mCorpusFullPath;
        char* mTargetFullPath;
        char** mTargetOption;
        char** mTargetEnv;
        int mSharedMemSize;
        int mPort;

    public:
        ~agent_cfg() {
            free_char_arr(mCorpusFullPath);
            free_char_arr(mTargetFullPath);
            free_char_arr_arr(mTargetEnv);
            free_char_arr_arr(mTargetOption);
        }

        int loadfile(const std::string& cfg_path) {
            std::ifstream cfg_file(cfg_path);
            if(cfg_file.is_open()) {
                std::stringstream buffer;
                buffer << cfg_file.rdbuf();
                std::string fileContent = buffer.str();
                payload_json_ = nlohmann::json::parse(fileContent);
                parse();
                return 0;
            }
            return -1;
        }
    private:
        void parse() {
            std::string tmp;
            std::vector<std::string> tmparr;
            if (payload_json_.contains("corpus_full_path") && payload_json_["corpus_full_path"].is_string()) {
                tmp = payload_json_["corpus_full_path"].get<std::string>();
                mCorpusFullPath = create_char_arr(tmp);
            } else {
                this->mCorpusFullPath = nullptr;
            }

            if (payload_json_.contains("target_full_path") && payload_json_["target_full_path"].is_string()) {
                tmp = payload_json_["target_full_path"].get<std::string>();
                mTargetFullPath = create_char_arr(tmp);
            } else {
                this->mTargetFullPath = nullptr;
            }

            if (payload_json_.contains("target_option") && payload_json_["target_option"].is_array()) {
                tmparr = payload_json_["target_option"].get<std::vector<std::string>>();
                mTargetOption = create_char_arr_arr(tmparr);
            } else {
                this->mTargetOption = nullptr;
            }

            if (payload_json_.contains("target_env") && payload_json_["target_env"].is_array()) {
                tmparr = payload_json_["target_env"].get<std::vector<std::string>>();
                mTargetEnv = create_char_arr_arr(tmparr);
            } else {
                this->mTargetEnv = nullptr;
            }

            if (payload_json_.contains("shared_mem_size") && payload_json_["shared_mem_size"].is_string()) {
                std::string mem_size = payload_json_["shared_mem_size"].get<std::string>();
                if(mem_size == "8M")
                    this->mSharedMemSize = SIZE_8MB;
                else if(mem_size == "64K")
                    this->mSharedMemSize = SIZE_64KB;
                else
                    this->mSharedMemSize = 0;
            } else {
                this->mSharedMemSize = 0;
            }
            if (payload_json_.contains("server_port") && payload_json_["server_port"].is_number_integer()) {
                this->mPort = payload_json_["server_port"].get<int>();
            } else {
                this->mPort=8080;//default
            }

        }
    public:
        static char** create_char_arr_arr(const std::vector<std::string>& strings) {
            char** arr = new char*[strings.size() + 1]; // +1 for the null pointer at the end

            for (size_t i = 0; i < strings.size(); i++) {
                const std::string& str = strings[i];
                char* charStr = new char[str.size() + 1];
                std::strcpy(charStr, str.c_str());
                arr[i] = charStr;
            }

            arr[strings.size()] = nullptr;

            return arr;
        }

        static void free_char_arr_arr(char** arr) {
            for (int i = 0; arr[i] != nullptr; i++) {
                delete[] arr[i];
            }

            delete[] arr;
        }
        static char* create_char_arr(const std::string& str){
            char* arr = new char[str.size() + 1];
            std::strcpy(arr, str.c_str());
            return arr;
        }
        static void free_char_arr(const char* arr){
            delete[] arr;
        }
    };

}


#endif //AGENT_CFG_HPP
